"Fossies" - the Fresh Open Source Software Archive

Member "google-gadgets-for-linux-0.11.2/gadgets/designer/designer_script_utils.cc" (28 Dec 2009, 14477 Bytes) of package /linux/misc/old/google-gadgets-for-linux-0.11.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /*
    2   Copyright 2008 Google Inc.
    3 
    4   Licensed under the Apache License, Version 2.0 (the "License");
    5   you may not use this file except in compliance with the License.
    6   You may obtain a copy of the License at
    7 
    8        http://www.apache.org/licenses/LICENSE-2.0
    9 
   10   Unless required by applicable law or agreed to in writing, software
   11   distributed under the License is distributed on an "AS IS" BASIS,
   12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   13   See the License for the specific language governing permissions and
   14   limitations under the License.
   15 */
   16 
   17 #include <algorithm>
   18 #include <cstring>
   19 #include <string>
   20 #include <vector>
   21 #include <ggadget/basic_element.h>
   22 #include <ggadget/color.h>
   23 #include <ggadget/file_manager_factory.h>
   24 #include <ggadget/file_manager_wrapper.h>
   25 #include <ggadget/gadget.h>
   26 #include <ggadget/gadget_consts.h>
   27 #include <ggadget/host_interface.h>
   28 #include <ggadget/logger.h>
   29 #include <ggadget/main_loop_interface.h>
   30 #include <ggadget/options_interface.h>
   31 #include <ggadget/permissions.h>
   32 #include <ggadget/scriptable_array.h>
   33 #include <ggadget/scriptable_binary_data.h>
   34 #include <ggadget/scriptable_helper.h>
   35 #include <ggadget/scriptable_menu.h>
   36 #include <ggadget/scriptable_view.h>
   37 #include <ggadget/script_context_interface.h>
   38 #include <ggadget/string_utils.h>
   39 #include <ggadget/system_utils.h>
   40 #include <ggadget/uuid.h>
   41 #include <ggadget/view_interface.h>
   42 
   43 namespace ggadget {
   44 namespace designer {
   45 
   46 static const char kGadgetFileManagerPrefix[] = "gadget://";
   47 static FileManagerInterface *g_gadget_file_manager = NULL;
   48 static FileManagerWrapper *g_designer_file_manager = NULL;
   49 static Gadget *g_designer_gadget = NULL;
   50 static Gadget *g_designee_gadget = NULL;
   51 static Connection *g_designee_close_connection = NULL;
   52 
   53 class ScriptableFileManager : public ScriptableHelperDefault {
   54  public:
   55   DEFINE_CLASS_ID(0x5a03aafca3094f1c, ScriptableInterface);
   56 
   57   ScriptableFileManager(FileManagerInterface *fm)
   58       : fm_(fm) {
   59   }
   60 
   61   virtual void DoRegister() {
   62     RegisterMethod("read",
   63                    NewSlot(this, &ScriptableFileManager::ReadFile));
   64     RegisterMethod("readBinary",
   65                    NewSlot(this, &ScriptableFileManager::ReadBinaryFile));
   66     RegisterMethod("write",
   67                    NewSlot(fm_, &FileManagerInterface::WriteFile));
   68     RegisterMethod("writeBinary",
   69                    NewSlot(this, &ScriptableFileManager::WriteBinaryFile));
   70     RegisterMethod("remove",
   71                    NewSlot(fm_, &FileManagerInterface::RemoveFile));
   72     RegisterMethod("extract",
   73                    NewSlot(this, &ScriptableFileManager::ExtractFile));
   74     RegisterMethod("exists",
   75                    NewSlot(this, &ScriptableFileManager::FileExists));
   76     RegisterMethod("isDirectlyAccessible",
   77                    NewSlot(this, &ScriptableFileManager::IsDirectlyAccessible));
   78     RegisterMethod("getFullPath",
   79                    NewSlot(fm_, &FileManagerInterface::GetFullPath));
   80     RegisterMethod("getLastModifiedTime",
   81                    NewSlot(this, &ScriptableFileManager::GetLastModifiedTime));
   82     RegisterMethod("getAllFiles",
   83                    NewSlot(this, &ScriptableFileManager::GetAllFiles));
   84     RegisterMethod("copy", NewSlot(this, &ScriptableFileManager::CopyFile));
   85   }
   86 
   87   std::string ReadFile(const char *file) {
   88     std::string result;
   89     fm_->ReadFile(file, &result);
   90     return result;
   91   }
   92 
   93   ScriptableBinaryData *ReadBinaryFile(const char *file) {
   94     std::string result;
   95     return fm_->ReadFile(file, &result) ?
   96            new ScriptableBinaryData(result) : NULL;
   97   }
   98 
   99   bool WriteBinaryFile(const char *file, ScriptableBinaryData *data,
  100                        bool overwrite) {
  101     if (!data)
  102       return false;
  103     return fm_->WriteFile(file, data->data(), overwrite);
  104   }
  105 
  106   std::string ExtractFile(const char *file) {
  107     std::string into_file;
  108     fm_->ExtractFile(file, &into_file);
  109     return into_file;
  110   }
  111 
  112   bool FileExists(const char *file) {
  113     return fm_->FileExists(file, NULL);
  114   }
  115 
  116   bool IsDirectlyAccessible(const char *file) {
  117     return fm_->IsDirectlyAccessible(file, NULL);
  118   }
  119 
  120   Date GetLastModifiedTime(const char *file) {
  121     return Date(fm_->GetLastModifiedTime(file));
  122   }
  123 
  124   static bool GetFile(const char *file, std::vector<std::string> *files) {
  125     files->push_back(file);
  126     return true;
  127   }
  128 
  129   ScriptableArray *GetAllFiles() {
  130     std::vector<std::string> files;
  131     fm_->EnumerateFiles("", NewSlot(GetFile, &files));
  132     return ScriptableArray::Create(files.begin(), files.end());
  133   }
  134 
  135   bool CopyFile(const char *src_file, const char *dest_file, bool overwrite) {
  136     std::string contents;
  137     return fm_->ReadFile(src_file, &contents) &&
  138            fm_->WriteFile(dest_file, contents, overwrite);
  139   }
  140 
  141   FileManagerInterface *fm_;
  142 };
  143 
  144 class DesignerUtils : public ScriptableHelperNativeOwnedDefault {
  145  public:
  146   DEFINE_CLASS_ID(0xd83de55b392c4d56, ScriptableInterface);
  147 
  148   DesignerUtils() {
  149     StringAppendPrintf(&designee_options_name_, "designee-options-%p", this);
  150   }
  151   ~DesignerUtils() {
  152     RemoveGadget();
  153   }
  154 
  155   virtual void DoRegister() {
  156     RegisterMethod("elementCoordToAncestor",
  157                    NewSlot(this, &DesignerUtils::ElementCoordToAncestor));
  158     RegisterMethod("ancestorCoordToElement",
  159                    NewSlot(this, &DesignerUtils::AncestorCoordToElement));
  160     RegisterMethod("isPointIn",
  161                    NewSlot(this, &DesignerUtils::IsPointIn));
  162     RegisterMethod("getOffsetPinX",
  163                    NewSlot(this, &DesignerUtils::GetOffsetPinX));
  164     RegisterMethod("getOffsetPinY",
  165                    NewSlot(this, &DesignerUtils::GetOffsetPinY));
  166     RegisterMethod("initGadgetFileManager",
  167                    NewSlot(this, &DesignerUtils::InitGadgetFileManager));
  168     RegisterMethod("getGlobalFileManager",
  169                    NewSlot(this, &DesignerUtils::GetGlobalFileManager));
  170     RegisterMethod("showXMLOptionsDialog",
  171                    NewSlot(this, &DesignerUtils::ShowXMLOptionsDialog));
  172     RegisterMethod("setDesignerMode",
  173                    NewSlot(this, &DesignerUtils::SetDesignerMode));
  174     RegisterMethod("systemOpenFileWith",
  175                    NewSlot(this, &DesignerUtils::SystemOpenFileWith));
  176     RegisterMethod("runGadget", NewSlot(this, &DesignerUtils::RunGadget));
  177     RegisterMethod("removeGadget", NewSlot(this, &DesignerUtils::RemoveGadget));
  178     RegisterMethod("generateUUID", NewSlot(GenerateUUID));
  179     RegisterMethod("getUserName", NewSlot(GetUserLoginName));
  180     RegisterMethod("parseColor", NewSlot(ParseColor));
  181     RegisterMethod("toColorString", NewSlot(ToColorString));
  182   }
  183 
  184   JSONString ElementCoordToAncestor(const BasicElement *element,
  185                                     const BasicElement *ancestor,
  186                                     double x, double y) {
  187     while (element && element != ancestor) {
  188       element->SelfCoordToParentCoord(x, y, &x, &y);
  189       element = element->GetParentElement();
  190     }
  191     return JSONString(StringPrintf("{\"x\":%f,\"y\":%f}", x, y));
  192   }
  193 
  194   JSONString AncestorCoordToElement(const BasicElement *ancestor,
  195                                     const BasicElement *element,
  196                                     double x, double y) {
  197     std::vector<const BasicElement *> path;
  198     while (element && element != ancestor) {
  199       path.push_back(element);
  200       element = element->GetParentElement();
  201     }
  202     for (size_t i = path.size(); i > 0; i--) {
  203       path[i - 1]->ParentCoordToSelfCoord(x, y, &x, &y);
  204     }
  205     return JSONString(StringPrintf("{\"x\":%f,\"y\":%f}", x, y));
  206   }
  207 
  208   bool IsPointIn(const BasicElement *element, double x, double y) {
  209     return element->IsPointIn(x, y);
  210   }
  211 
  212   double GetOffsetPinX(const BasicElement *element) {
  213     return element->GetPixelPinX();
  214   }
  215 
  216   double GetOffsetPinY(const BasicElement *element) {
  217     return element->GetPixelPinY();
  218   }
  219 
  220   ScriptableFileManager *InitGadgetFileManager(const char *gadget_path) {
  221     if (!gadget_path || !*gadget_path)
  222       return NULL;
  223 
  224     if (g_gadget_file_manager) {
  225       g_designer_file_manager->UnregisterFileManager(kGadgetFileManagerPrefix,
  226                                                      g_gadget_file_manager);
  227       delete g_gadget_file_manager;
  228     }
  229     std::string path, filename;
  230     SplitFilePath(gadget_path, &path, &filename);
  231 
  232     // Uses the parent path of base_path if it refers to a manifest file.
  233     if (filename != kGadgetGManifest)
  234       path = gadget_path;
  235 
  236     g_gadget_file_manager = CreateFileManager(path.c_str());
  237     if (g_gadget_file_manager) {
  238       g_designer_file_manager->RegisterFileManager(kGadgetFileManagerPrefix,
  239                                                    g_gadget_file_manager);
  240       return new ScriptableFileManager(g_gadget_file_manager);
  241     }
  242     return NULL;
  243   }
  244 
  245   ScriptableFileManager *GetGlobalFileManager() {
  246     return new ScriptableFileManager(::ggadget::GetGlobalFileManager());
  247   }
  248 
  249   void ShowXMLOptionsDialog(const char *xml_file, ScriptableInterface *param) {
  250     g_designer_gadget->ShowXMLOptionsDialog(
  251         ViewInterface::OPTIONS_VIEW_FLAG_OK |
  252         ViewInterface::OPTIONS_VIEW_FLAG_CANCEL,
  253         xml_file, param);
  254   }
  255 
  256   void SetDesignerMode(BasicElement *element) {
  257     element->SetDesignerMode(true);
  258   }
  259 
  260   void SystemOpenFileWith(const char *command, const char *file) {
  261     pid_t pid;
  262     // fork and run the command.
  263     if ((pid = fork()) == 0) {
  264       if (fork() != 0)
  265         _exit(0);
  266       execlp(command, command, file, NULL);
  267       DLOG("Failed to exec command: %s", command);
  268       _exit(-1);
  269     }
  270   }
  271 
  272   class RunGadgetWatchCallback : public WatchCallbackInterface {
  273    public:
  274     RunGadgetWatchCallback(const std::string &gadget_path,
  275                            const std::string &options_name)
  276         : gadget_path_(gadget_path), options_name_(options_name) {
  277     }
  278 
  279     virtual bool Call(MainLoopInterface *main_loop, int watch_id) {
  280       GGL_UNUSED(main_loop);
  281       GGL_UNUSED(watch_id);
  282       // The gadget manager always use positive instance ids, so this designee_id
  283       // won't conflict with them.
  284       int designee_id = -g_designer_gadget->GetInstanceID() - 1;
  285       if (designee_id >= 0) {
  286         LOG("This designer can't run gadgets if the designer is running in "
  287             "another designer");
  288         return false;
  289       }
  290 
  291       StringMap manifest;
  292       Permissions permissions;
  293       if (Gadget::GetGadgetManifest(gadget_path_.c_str(), &manifest)) {
  294         Gadget::GetGadgetRequiredPermissions(&manifest, &permissions);
  295         permissions.GrantAllRequired();
  296         Gadget::SaveGadgetInitialPermissions(options_name_.c_str(),
  297                                              permissions);
  298       } else {
  299         LOG("Failed to load gadget's required permissions information.");
  300       }
  301 
  302       g_designee_gadget = g_designer_gadget->GetHost()->LoadGadget(
  303           gadget_path_.c_str(), options_name_.c_str(), designee_id, true);
  304 
  305       if (g_designee_gadget && g_designee_gadget->IsValid()) {
  306         g_designee_gadget->ShowMainView();
  307         g_designee_close_connection = g_designee_gadget->GetMainView()->
  308             ConnectOnCloseEvent(NewSlot(ResetDesigneeGadget));
  309       }
  310       return false;
  311     }
  312 
  313     virtual void OnRemove(MainLoopInterface *main_loop, int watch_id) {
  314       GGL_UNUSED(main_loop);
  315       GGL_UNUSED(watch_id);
  316       delete this;
  317     }
  318 
  319     static void ResetDesigneeGadget() {
  320       g_designee_gadget = NULL;
  321     }
  322 
  323    private:
  324     std::string gadget_path_;
  325     std::string options_name_;
  326   };
  327 
  328   void RunGadget(const char *gadget_path) {
  329     if (!gadget_path || !*gadget_path)
  330       return;
  331 
  332     RemoveGadget();
  333     // Schedule actual gadget run, because Gadget::RemoveMe() scheduled the
  334     // actual gadget removal in the next main loop.
  335     GetGlobalMainLoop()->AddTimeoutWatch(
  336         0, new RunGadgetWatchCallback(gadget_path, designee_options_name_));
  337   }
  338 
  339   void RemoveGadget() {
  340     if (g_designee_gadget) {
  341       g_designee_close_connection->Disconnect();
  342       g_designee_gadget->RemoveMe(false);
  343       g_designee_gadget = NULL;
  344     }
  345 
  346     OptionsInterface *options = CreateOptions(designee_options_name_.c_str());
  347     if (options) {
  348       options->DeleteStorage();
  349       delete options;
  350     }
  351   }
  352 
  353   static std::string GenerateUUID() {
  354     UUID uuid;
  355     uuid.Generate();
  356     return uuid.GetString();
  357   }
  358 
  359   static JSONString ParseColor(const char *color_str) {
  360     Color color;
  361     double opacity = 0;
  362     if (!Color::FromString(color_str, &color, &opacity))
  363       return JSONString("");
  364     return JSONString(StringPrintf(
  365         "{\"red\":%d,\"green\":%d,\"blue\":%d,\"opacity\":%d}",
  366         color.RedInt(), color.GreenInt(), color.BlueInt(),
  367         static_cast<int>(round(opacity * 255))));
  368   }
  369 
  370   static std::string ToColorString(int r, int g, int b, int opacity) {
  371     r = std::min(255, std::max(0, r));
  372     g = std::min(255, std::max(0, g));
  373     b = std::min(255, std::max(0, b));
  374     opacity = std::min(255, std::max(0, opacity));
  375     return opacity == 255 ? StringPrintf("#%02X%02X%02X", r, g, b) :
  376                             StringPrintf("#%02X%02X%02X%02X", opacity, r, g, b);
  377   }
  378 
  379  private:
  380   std::string designee_options_name_;
  381 };
  382 
  383 static DesignerUtils g_designer_utils;
  384 
  385 } // namespace designer
  386 } // namespace ggadget
  387 
  388 #define Initialize designer_script_utils_LTX_Initialize
  389 #define Finalize designer_script_utils_LTX_Finalize
  390 #define RegisterScriptExtension \
  391     designer_script_utils_LTX_RegisterScriptExtension
  392 #define RegisterFileManagerExtension \
  393     designer_script_utils_LTX_RegisterFileManagerExtension
  394 
  395 extern "C" {
  396   bool Initialize() {
  397     LOGI("Initialize designer_script_utils extension.");
  398     return true;
  399   }
  400 
  401   void Finalize() {
  402     LOGI("Finalize designer_script_utils extension.");
  403   }
  404 
  405   bool RegisterScriptExtension(ggadget::ScriptContextInterface *context,
  406                                ggadget::Gadget *gadget) {
  407     ASSERT(context);
  408     ASSERT(gadget);
  409     if (context) {
  410       if (!context->AssignFromNative(
  411           NULL, NULL, "designerUtils",
  412           ggadget::Variant(&ggadget::designer::g_designer_utils))) {
  413         LOG("Failed to register designerUtils.");
  414         return false;
  415       }
  416       ggadget::designer::g_designer_gadget = gadget;
  417       return true;
  418     }
  419     return false;
  420   }
  421 
  422   bool RegisterFileManagerExtension(ggadget::FileManagerWrapper *fm) {
  423     LOGI("Register designer_script_utils file manager extension.");
  424     ASSERT(fm);
  425     ggadget::designer::g_designer_file_manager = fm;
  426     return true;
  427   }
  428 }